/*
 * =====================================================================================
 *
 *       Filename:  watcher.h
 *
 *    Description:  用来监控事件发生的类
 *
 *        Version:  0.1
 *        Created:  2011年03月24日 17时29分33秒
 *        Updated:  2011年04月19日 00时50分07秒
 *
 *      Copyright:  (c) 2011,lgy
 *       Compiler:  gcc
 *
 *         Author:  lgy
 *         School:  ssdut
 *
 * =====================================================================================
 */
#ifndef WATCHER_H
#define WATCHER_H
#include <sys/types.h>
#include <sys/inotify.h>
#include <iostream>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <signal.h>
#include <vector>
#include <fcntl.h>
#include <list>
#include <string>
#include <utility>
#include <map>
#include <sys/select.h>
#include <cstring>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <string.h>
#include <QObject>
#include <QDir>
#include <QString>
#include <QFile>
#include <QTextStream>
#include <QStringList>
#include <QMap>
#include <QThread>
#include <QTextCodec>
#include <QMessageBox>
#include "ievent.h"
#include "gheaders.h"
#include "tcp_routines.h"
using namespace std;

#define event_size (sizeof(struct inotify_event)) //定义事件结构体长度
#define buf_len (1024*(event_size + 16 ))         //定义缓冲区大小

class watcher:public QThread
{
    Q_OBJECT
    private:
        char buff[buf_len];                       //读取事件时候用的存储区
        list<ievent*> fliterlist;                  //用来存储需要存储的事件序列
        list<ievent*> processlist;                       //再定义一个队列，用来帮助处理弹栈压栈事件
        map<int,string>watchers;                  //将wd值和文件夹名字利用图对应起来
        int wd;
        int fd;
        fd_set fdset;                             //文件描述符集，用于select函数
        bool isUpdating;                          //一个变量，用来标志是否处在更新事件中
        bool isMoveIning;                         //一个变量，用来标志是否处在移进文件夹事件
        QMap<QString,int> updateMap;              //一个图，用来记录和判断应该给一个文件打上什么样的徽标
        QList<QString> fileToUpdate;              //用来记录需要上传的文件
        struct timeval timer;                     //时间结构体，用于select函数
        int ctl_sock;                             //传输控制信息的socket
        int tsf_sock;                             //用于传递数据包的socket
        string userName;                          //登录用户的名字
        QString workDir;                          //监控的文件夹
        long useAge;
        int ctl_update(uint8_t type, const string& path1, const string& path2=""); //上传控制信息的函数
        int data_update(QString path);            //上传文件的函数
    public:
        bool Running;
        bool hasUpdated;                          //判断是否在更新
        bool isSendingData;

        watcher();
        watcher(string dirName,int argSockedFd,string argUserName,long useage); //带参数构造函数，参数：监控目录，tcp控制文件描述符，用户名
        //QThread使用的run函数，用来启动多线程
        void run()
        {
            watch();
        }
        void watch();                             //监控函数
        string getdirOnwd(int wd);                //根据wd值获得文件夹明
        int getwd(string);                        //根据文件夹名获得wd值
        void fliter();                            //事件的过滤和处理函数
        void addDir(string dirname);              //向监控中添加文件夹函数
        void moveInDir(string dirname,int pwd);           //移入文件夹时候做的操作
        void process();                           //处理processlist中的事件（主要是删除和移动）
        bool isEmptyDir(string dirname);
        void EmblemUpdating(QString);
        void EmblemUpdated(QString);
        void setIconUpdate(QString filename);             //设置图标为同步中
        void setIconFinished(QString filename);           //设置图标为同步完成
        void setIconUpdateFailed(QString filename);

        void SearchFile(QString);
        void rmFromIconMap(QString);
        long countSizeForDir(const char* name);
        long countSizeForFile(const char* name);
        void overSize(QString name);
        int& getTsf_socket();
        void clearWatcher();
    signals:
        void updating();                          //向Controller发送的信号，用来提示正在更新中
        void hasChanged();                        //像Controller发送的函数，反映正在跟新中
        void setEmblemUpdating();                 //向Controller发送的函数，用来提示什么时候要更新托盘图标
        void setEmblemUpdated();
        void sizeChanged(long);
        void sigOverSize(QString);
};


#endif // WATCHER_H
